package HLLib.userControl;

import java.io.ByteArrayOutputStream;

import HLCode.HLClass;
import HLCode.HLClassManager;
import HLCode.HLClassManager_H;
import HLCode.HLLibObject;
import HLLib.base.HLByteList;
import HLLib.base.HLString;

public class HLBase64 extends HLLibObject {
    public HLClass GetClass(HLClassManager classManager) {
        return classManager.GetLibClass(HLClassManager_H.CLASS_GROUP_TYPE_LIB_USERCONTROL, HLClassManager_H.LIB_CLASS_USERCONTROL_Base64);
    }

	private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D',
			'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
			'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
			'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
			'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
			'4', '5', '6', '7', '8', '9', '+', '/' };
	private static char[] base64EncodeCharsEx = new char[] { '0', '1', '2',
			'3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
			'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
			't', 'u', 'v', 'w', 'x', 'y', 'z', '+', '/', 'A', 'B', 'C', 'D',
			'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
			'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
	private static char[] Base64ReplaceMap;
	private static char[] Base64ReplaceMapEx;
	private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
			60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
			10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
			-1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
			38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
			-1, -1 };

	// static const char Base64[] =
	// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	// static char * Base64ReplaceMap = null;
	//
	// static const char Base64Ex[] =
	// "0123456789abcdefghijklmnopqrstuvwxyz+/ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	public HLBase64() {
	}

	private static void Init() {
		Base64ReplaceMap = new char[128];
		Base64ReplaceMapEx = new char[128];
		for (int i = 0; i < 64; i++) {
			Base64ReplaceMap[base64EncodeChars[i]] = base64EncodeCharsEx[i];
			Base64ReplaceMapEx[base64EncodeCharsEx[i]] = base64EncodeChars[i];
		}
	}

	public static HLString encode(HLByteList data) {
		return new HLString(encode1(data.items));
	}

	public static HLByteList decode(HLString str) {
		return new HLByteList(decode1(str.string));
	}

	public static HLString encodeEx(HLByteList data, boolean isSafeUrl,
			boolean isHandfere) {
		if (Base64ReplaceMap == null) {
			Init();
		}
		HLString result = encode(data);
		if (isHandfere) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < result.Length(); i++) {
				char tmp = result.CharAt(i);
				char tmp1 ;
				if(tmp=='='||tmp=='\r'){
					tmp1 = tmp;
				}else{
					 tmp1 = Base64ReplaceMap[tmp];
				}
				sb.append(tmp1);
			}
			result.string = sb.toString();
		}
		if (isSafeUrl) {
			result = UrlEncode(result);
		}
		return result;
	}

	public static HLByteList decodeEx(HLString str, boolean isSafeUrl,
			boolean isHandfere) {
		if (Base64ReplaceMap == null) {
			Init();
		}
		if (isSafeUrl) {
			str = UrlDecode(str);
		}
		if (isHandfere) {
			StringBuffer sb = new StringBuffer();
    		for(int i = 0;i < str.Length();i++){
    			char tmp = str.CharAt(i);
    			char tmp1 ;
				if(tmp=='='||tmp=='\r'){
					tmp1 = tmp;
				}else{
					 tmp1 = Base64ReplaceMapEx[tmp];
				}
    			sb.append(tmp1);
    		}
    		str.string = sb.toString();
		}
		return decode(str);
	}

	public static String encode1(byte[] data) {
		StringBuffer sb = new StringBuffer();
		int len = data.length;
		int i = 0;
		int b1, b2, b3;

		while (i < len) {
			b1 = data[i++] & 0xff;
			if (i == len) {
				sb.append(base64EncodeChars[b1 >>> 2]);
				sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
				sb.append("==");
				break;
			}
			b2 = data[i++] & 0xff;
			if (i == len) {
				sb.append(base64EncodeChars[b1 >>> 2]);
				sb.append(base64EncodeChars[((b1 & 0x03) << 4)
						| ((b2 & 0xf0) >>> 4)]);
				sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
				sb.append("=");
				break;
			}
			b3 = data[i++] & 0xff;
			sb.append(base64EncodeChars[b1 >>> 2]);
			sb.append(base64EncodeChars[((b1 & 0x03) << 4)
					| ((b2 & 0xf0) >>> 4)]);
			sb.append(base64EncodeChars[((b2 & 0x0f) << 2)
					| ((b3 & 0xc0) >>> 6)]);
			sb.append(base64EncodeChars[b3 & 0x3f]);
		}
		return sb.toString();
	}

	public static byte[] decode1(String str) {
		byte[] data = str.getBytes();
		int len = data.length;
		ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
		int i = 0;
		int b1, b2, b3, b4;

		while (i < len) {

			/* b1 */
			do {
				b1 = base64DecodeChars[data[i++]];
			} while (i < len && b1 == -1);
			if (b1 == -1) {
				break;
			}

			/* b2 */
			do {
				b2 = base64DecodeChars[data[i++]];
			} while (i < len && b2 == -1);
			if (b2 == -1) {
				break;
			}
			buf.write(((b1 << 2) | ((b2 & 0x30) >>> 4)));

			/* b3 */
			do {
				b3 = data[i++];
				if (b3 == 61) {
					return buf.toByteArray();
				}
				b3 = base64DecodeChars[b3];
			} while (i < len && b3 == -1);
			if (b3 == -1) {
				break;
			}
			buf.write((((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

			/* b4 */
			do {
				b4 = data[i++];
				if (b4 == 61) {
					return buf.toByteArray();
				}
				b4 = base64DecodeChars[b4];
			} while (i < len && b4 == -1);
			if (b4 == -1) {
				break;
			}
			buf.write((((b3 & 0x03) << 6) | b4));
		}
		return buf.toByteArray();
	}

	public static HLString UrlEncode(HLString string) {
		return new HLString(UrlEncode1(string.string));
	}

	public static HLString UrlDecode(HLString string) {
		return new HLString(UrlDecode1(string.string));
	}

	public static String UrlEncode1(String string) {
		String result = string.replace('+', '*');
		result = result.replace('/', '-');
		return result;
	}

	public static String UrlDecode1(String string) {
		String result = string.replace('*', '+');
		result = result.replace('-', '/');
		return result;
	}
	public static void test(){
		HLString tmp = new HLString("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
		System.out.println(tmp.string);
		tmp = encodeEx(tmp.GetBytes(), true, true);
		System.out.println(tmp.string);
		tmp = new HLString("uM9Pgnpxt65M8zCyq7hOs3CJbQcIq65Ip6p-sAkIoQXHbQd-rBh-syXDrm5BpncJrAXxtA5Oon9ve30IpQ-A8yKyrA5OqmXI8zCyoQSyb29ys6pMqmlIp7cyey8yb29Npnwyey8L8yKyoB0yey98hy8G8A9KomdzrRlIt28UcNgLdjwPb29ys65Pt6wyey8Np6gQem9-oPxCszkSlP5joRldklhHtzoQr4sOdmXdpmTAs64LolCTd*9IcAtHhPDIs5pxjkh8omgSgnDpiAtNiRlipQWQdnhfdQ53s79NmzxOaRdIu6LghzkK8yKyrR0yey9NumTzj6XBqmSyvg==");
		tmp = HLString.ValueOfByteList(decodeEx(tmp, true, true));
		System.out.println(tmp.string);
		
	}
}
